bitkeeper revision 1.1308 (4260510bQdQyEJ4w-XdZSU5iSTB_Pg)
authoriap10@freefall.cl.cam.ac.uk <iap10@freefall.cl.cam.ac.uk>
Fri, 15 Apr 2005 23:40:59 +0000 (23:40 +0000)
committeriap10@freefall.cl.cam.ac.uk <iap10@freefall.cl.cam.ac.uk>
Fri, 15 Apr 2005 23:40:59 +0000 (23:40 +0000)
The attached patch apic.patch updates xen/arch/x86/apic.c so that it is based on linux 2.6.10 code.  A few changes made to linux required reworking functions in other files as well so I held off on those changes.  For example, setup_APIC_timer(void *) changed to setup_APIC_timer(unsigned int).  The change has no real bearing on the Xen code -- it's just a question of how close to linux one wants to be.  However, that change goes with a change to smp_call_function which would affect quite a few other files/functions so I left it as is.  Most of the other changes are trivial.
xen/ac_timer.h was included but not needed by apic.c so I removed it from the list of #includes.

The new apic.c includes two new files: asm/io_ports.h and asm/mach_apic.h.  Patches to create those files are included as well.

.rootkeys
xen/arch/x86/apic.c
xen/include/asm-x86/io_ports.h [new file with mode: 0644]
xen/include/asm-x86/mach_apic.h [new file with mode: 0644]

index 95fbaf200c07977b8241fd743684e30227f4b280..6c7e1b42320c76366743aae350d7377c3f1a781c 100644 (file)
--- a/.rootkeys
+++ b/.rootkeys
 4204e7acwXDo-5iAAiO2eQbtDeYZXA xen/include/asm-x86/init.h
 3ddb79c3fQ_O3o5NHK2N8AJdk0Ea4Q xen/include/asm-x86/io.h
 3ddb79c2TKeScYHQZreTdHqYNLbehQ xen/include/asm-x86/io_apic.h
+42605109qxLSrHVE2SRhGXmgk907iw xen/include/asm-x86/io_ports.h
 3ddb79c2L7rTlFzazOLW1XuSZefpFw xen/include/asm-x86/irq.h
 404f1b93OjLO4bFfBXYNaJdIqlNz-Q xen/include/asm-x86/ldt.h
+4260510aYPj2kr6rMbBfMxcvvmXndQ xen/include/asm-x86/mach_apic.h
 3ddb79c3I98vWcQR8xEo34JMJ4Ahyw xen/include/asm-x86/mc146818rtc.h
 40ec25fd7cSvbP7Biw91zaU_g0xsEQ xen/include/asm-x86/mm.h
 3ddb79c3n_UbPuxlkNxvvLycClIkxA xen/include/asm-x86/mpspec.h
index 49b51ba01226eca1e718f46d4fe825e57a1aaaa2..9b44fb6f986006f0011152e950bf9e7bd8f54016 100644 (file)
@@ -1,4 +1,6 @@
 /*
+ *      based on linux-2.6.10/arch/i386/kernel/apic.c
+ *
  *  Local APIC handling, local APIC timers
  *
  *  (c) 1999, 2000 Ingo Molnar <mingo@redhat.com>
  *                  for testing these extensively.
  *     Maciej W. Rozycki       :       Various updates and fixes.
  *     Mikael Pettersson       :       Power Management for UP-APIC.
+ *    Pavel Machek and
+ *    Mikael Pettersson    :    PM converted to driver model.
  */
 
-
 #include <xen/config.h>
-#include <xen/ac_timer.h>
 #include <xen/perfc.h>
 #include <xen/errno.h>
 #include <xen/init.h>
@@ -32,7 +34,8 @@
 #include <asm/hardirq.h>
 #include <asm/apic.h>
 #include <asm/io_apic.h>
-
+#include <asm/mach_apic.h>
+#include <asm/io_ports.h>
 
 /* Using APIC to generate smp_local_timer_interrupt? */
 int using_apic_timer = 0;
@@ -80,6 +83,16 @@ void clear_local_APIC(void)
         apic_write_around(APIC_LVTPC, v | APIC_LVT_MASKED);
     }
 
+#if 0
+/* lets not touch this if we didn't frob it */
+#ifdef CONFIG_X86_MCE_P4THERMAL
+    if (maxlvt >= 5) {
+        v = apic_read(APIC_LVTTHMR);
+        apic_write_around(APIC_LVTTHMR, v | APIC_LVT_MASKED);
+    }
+#endif
+#endif
+
     /*
      * Clean APIC state for other OSs:
      */
@@ -90,9 +103,17 @@ void clear_local_APIC(void)
         apic_write_around(APIC_LVTERR, APIC_LVT_MASKED);
     if (maxlvt >= 4)
         apic_write_around(APIC_LVTPC, APIC_LVT_MASKED);
+
+#if 0
+#ifdef CONFIG_X86_MCE_P4THERMAL
+    if (maxlvt >= 5)
+        apic_write_around(APIC_LVTTHMR, APIC_LVT_MASKED);
+#endif
+#endif 
+
     v = GET_APIC_VERSION(apic_read(APIC_LVR));
     if (APIC_INTEGRATED(v)) {  /* !82489DX */
-        if (maxlvt > 3)
+        if (maxlvt > 3)        /* Due to Pentium errata 3AP and 11AP. */
             apic_write(APIC_ESR, 0);
         apic_read(APIC_ESR);
     }
@@ -113,6 +134,9 @@ void __init connect_bsp_APIC(void)
         outb(0x70, 0x22);
         outb(0x01, 0x23);
     }
+#if 0
+    enable_apic_mode();
+#endif
 }
 
 void disconnect_bsp_APIC(void)
@@ -193,12 +217,6 @@ int __init verify_local_APIC(void)
      */
     reg0 = apic_read(APIC_ID);
     Dprintk("Getting ID: %x\n", reg0);
-    apic_write(APIC_ID, reg0 ^ APIC_ID_MASK);
-    reg1 = apic_read(APIC_ID);
-    Dprintk("Getting ID: %x\n", reg1);
-    apic_write(APIC_ID, reg0);
-    if (reg1 != (reg0 ^ APIC_ID_MASK))
-        return 0;
 
     /*
      * The next two are just to see if we have sane values.
@@ -215,6 +233,10 @@ int __init verify_local_APIC(void)
 
 void __init sync_Arb_IDs(void)
 {
+    /* Unsupported on P4 - see Intel Dev. Manual Vol. 3, Ch. 8.6.1 */
+    unsigned int ver = GET_APIC_VERSION(apic_read(APIC_LVR));
+    if (ver >= 0x14)    /* P4 or higher */
+        return;
     /*
      * Wait for idle.
      */
@@ -240,15 +262,17 @@ void __init init_bsp_APIC(void)
 {
 }
 
-static unsigned long calculate_ldr(unsigned long old)
-{
-    unsigned long id = 1UL << smp_processor_id();
-    return (old & ~APIC_LDR_MASK)|SET_APIC_LOGICAL_ID(id);
-}
-
 void __init setup_local_APIC (void)
 {
-    unsigned long value, ver, maxlvt;
+    unsigned long oldvalue, value, ver, maxlvt;
+
+    /* Pound the ESR really hard over the head with a big hammer - mbligh */
+    if (esr_disable) {
+        apic_write(APIC_ESR, 0);
+        apic_write(APIC_ESR, 0);
+        apic_write(APIC_ESR, 0);
+        apic_write(APIC_ESR, 0);
+    }
 
     value = apic_read(APIC_LVR);
     ver = GET_APIC_VERSION(value);
@@ -256,8 +280,10 @@ void __init setup_local_APIC (void)
     if ((SPURIOUS_APIC_VECTOR & 0x0f) != 0x0f)
         __error_in_apic_c();
 
-    /* Double-check wether this APIC is really registered. */
-    if (!test_bit(GET_APIC_ID(apic_read(APIC_ID)), &phys_cpu_present_map))
+    /*
+     * Double-check whether this APIC is really registered.
+     */
+    if (!apic_id_registered())
         BUG();
 
     /*
@@ -265,19 +291,7 @@ void __init setup_local_APIC (void)
      * an APIC.  See e.g. "AP-388 82489DX User's Manual" (Intel
      * document number 292116).  So here it goes...
      */
-
-    /*
-     * In clustered apic mode, the firmware does this for us 
-     * Put the APIC into flat delivery mode.
-     * Must be "all ones" explicitly for 82489DX.
-     */
-    apic_write_around(APIC_DFR, APIC_DFR_FLAT);
-
-    /*
-     * Set up the logical destination ID.
-     */
-    value = apic_read(APIC_LDR);
-    apic_write_around(APIC_LDR, calculate_ldr(value));
+    init_apic_ldr();
 
     /*
      * Set Task Priority to 'accept all'. We never change this
@@ -297,10 +311,35 @@ void __init setup_local_APIC (void)
      */
     value |= APIC_SPIV_APIC_ENABLED;
 
+    /*
+     * Some unknown Intel IO/APIC (or APIC) errata is biting us with
+     * certain networking cards. If high frequency interrupts are
+     * happening on a particular IOAPIC pin, plus the IOAPIC routing
+     * entry is masked/unmasked at a high rate as well then sooner or
+     * later IOAPIC line gets 'stuck', no more interrupts are received
+     * from the device. If focus CPU is disabled then the hang goes
+     * away, oh well :-(
+     *
+     * [ This bug can be reproduced easily with a level-triggered
+     *   PCI Ne2000 networking cards and PII/PIII processors, dual
+     *   BX chipset. ]
+     */
+    /*
+     * Actually disabling the focus CPU check just makes the hang less
+     * frequent as it makes the interrupt distributon model be more
+     * like LRU than MRU (the short-term load is more even across CPUs).
+     * See also the comment in end_level_ioapic_irq().  --macro
+     */
+#if 1
     /* Enable focus processor (bit==0) */
     value &= ~APIC_SPIV_FOCUS_DISABLED;
-
-    /* Set spurious IRQ vector */
+#else
+    /* Disable focus processor (bit==1) */
+    value |= APIC_SPIV_FOCUS_DISABLED;
+#endif
+    /*
+     * Set spurious IRQ vector
+     */
     value |= SPURIOUS_APIC_VECTOR;
     apic_write_around(APIC_SPIV, value);
 
@@ -315,7 +354,7 @@ void __init setup_local_APIC (void)
      * TODO: set up through-local-APIC from through-I/O-APIC? --macro
      */
     value = apic_read(APIC_LVT0) & APIC_LVT_MASKED;
-    if (!smp_processor_id()) { 
+    if (!smp_processor_id() && (pic_mode || !value)) {
         value = APIC_DM_EXTINT;
         printk("enabled ExtINT on CPU#%d\n", smp_processor_id());
     } else {
@@ -335,33 +374,43 @@ void __init setup_local_APIC (void)
         value |= APIC_LVT_LEVEL_TRIGGER;
     apic_write_around(APIC_LVT1, value);
 
-    if (APIC_INTEGRATED(ver)) {     /* !82489DX */
+    if (APIC_INTEGRATED(ver) && !esr_disable) {        /* !82489DX */
         maxlvt = get_maxlvt();
         if (maxlvt > 3)     /* Due to the Pentium erratum 3AP. */
             apic_write(APIC_ESR, 0);
-        value = apic_read(APIC_ESR);
-        printk("ESR value before enabling vector: %08lx\n", value);
+        oldvalue = apic_read(APIC_ESR);
 
-        value = ERROR_APIC_VECTOR;      /* enables sending errors */
+        value = ERROR_APIC_VECTOR;      // enables sending errors
         apic_write_around(APIC_LVTERR, value);
-        /* spec says clear errors after enabling vector. */
+        /*
+         * spec says clear errors after enabling vector.
+         */
         if (maxlvt > 3)
             apic_write(APIC_ESR, 0);
         value = apic_read(APIC_ESR);
-        printk("ESR value after enabling vector: %08lx\n", value);
+        if (value != oldvalue)
+            printk("ESR value before enabling vector: 0x%08lx "
+                "after: 0x%08lx\n", oldvalue, value);
     } else {
+        if (esr_disable)    
+            /* 
+             * Something untraceble is creating bad interrupts on 
+             * secondary quads ... for the moment, just leave the
+             * ESR disabled - we can't do anything useful with the
+             * errors anyway - mbligh
+             */
+            printk("Leaving ESR disabled.\n");
+        else 
         printk("No ESR for 82489DX.\n");
     }
 
-    if ( (smp_processor_id() == 0) && (nmi_watchdog == NMI_LOCAL_APIC) )
+    if (nmi_watchdog == NMI_LOCAL_APIC)
         setup_apic_nmi_watchdog();
+#if 0
+    apic_pm_activate();
+#endif
 }
 
-
-static inline void apic_pm_init1(void) { }
-static inline void apic_pm_init2(void) { }
-
-
 /*
  * Detect and enable local APICs on non-SMP boards.
  * Original code written by Keir Fraser.
@@ -372,19 +421,23 @@ static int __init detect_init_APIC (void)
     u32 h, l, features;
     extern void get_cpu_vendor(struct cpuinfo_x86*);
 
+#if 0
+    /* Disabled by kernel option? */
+    if (enable_local_apic < 0)
+        return -1;
+#endif
+
     /* Workaround for us being called before identify_cpu(). */
     get_cpu_vendor(&boot_cpu_data);
 
     switch (boot_cpu_data.x86_vendor) {
     case X86_VENDOR_AMD:
-        if (boot_cpu_data.x86 == 6 && boot_cpu_data.x86_model > 1)
-            break;
-        if (boot_cpu_data.x86 == 15 && cpu_has_apic)
+        if ((boot_cpu_data.x86 == 6 && boot_cpu_data.x86_model > 1) ||
+            (boot_cpu_data.x86 == 15))        
             break;
         goto no_apic;
     case X86_VENDOR_INTEL:
-        if (boot_cpu_data.x86 == 6 ||
-            (boot_cpu_data.x86 == 15 && cpu_has_apic) ||
+        if (boot_cpu_data.x86 == 6 || boot_cpu_data.x86 == 15 ||
             (boot_cpu_data.x86 == 5 && cpu_has_apic))
             break;
         goto no_apic;
@@ -393,10 +446,22 @@ static int __init detect_init_APIC (void)
     }
 
     if (!cpu_has_apic) {
+        /*
+         * Over-ride BIOS and try to enable the local
+         * APIC only if "lapic" specified.
+         */
+#if 0
+        if (enable_local_apic <= 0) {
+            printk("Local APIC disabled by BIOS -- "
+                   "you can enable it with \"lapic\"\n");
+            return -1;
+        }
+#endif
         /*
          * Some BIOSes disable the local APIC in the
          * APIC_BASE MSR. This can only be done in
-         * software for Intel P6 and AMD K7 (Model > 1).
+         * software for Intel P6 or later and AMD K7
+         * (Model > 1) or later.
          */
         rdmsr(MSR_IA32_APICBASE, l, h);
         if (!(l & MSR_IA32_APICBASE_ENABLE)) {
@@ -407,17 +472,17 @@ static int __init detect_init_APIC (void)
             enabled_via_apicbase = 1;
         }
     }
-
-    /* The APIC feature bit should now be enabled in `cpuid' */
+    /*
+     * The APIC feature bit should now be enabled
+     * in `cpuid'
+     */
     features = cpuid_edx(1);
     if (!(features & (1 << X86_FEATURE_APIC))) {
         printk("Could not enable APIC!\n");
         return -1;
     }
-
-    set_bit(X86_FEATURE_APIC, &boot_cpu_data.x86_capability);
+    set_bit(X86_FEATURE_APIC, boot_cpu_data.x86_capability);
     mp_lapic_addr = APIC_DEFAULT_PHYS_BASE;
-    boot_cpu_physical_apicid = 0;
 
     /* The BIOS may have set up the APIC at some other address */
     rdmsr(MSR_IA32_APICBASE, l, h);
@@ -428,21 +493,26 @@ static int __init detect_init_APIC (void)
                nmi_watchdog = NMI_LOCAL_APIC;
 
     printk("Found and enabled local APIC!\n");
-    apic_pm_init1();
+
+#if 0
+    apic_pm_activate();
+#endif
+
     return 0;
 
- no_apic:
+no_apic:
     printk("No local APIC present or hardware disabled\n");
     return -1;
 }
 
 void __init init_apic_mappings(void)
 {
-    unsigned long apic_phys = 0;
+    unsigned long apic_phys;
 
     /*
-     * If no local APIC can be found then set up a fake all zeroes page to 
-     * simulate the local APIC and another one for the IO-APIC.
+     * If no local APIC can be found then set up a fake all
+     * zeroes page to simulate the local APIC and another
+     * one for the IO-APIC.
      */
     if (!smp_found_config && detect_init_APIC()) {
         apic_phys = alloc_xenheap_page();
@@ -462,12 +532,26 @@ void __init init_apic_mappings(void)
 
 #ifdef CONFIG_X86_IO_APIC
     {
-        unsigned long ioapic_phys = 0, idx = FIX_IO_APIC_BASE_0;
+        unsigned long ioapic_phys, idx = FIX_IO_APIC_BASE_0;
         int i;
 
         for (i = 0; i < nr_ioapics; i++) {
-            if (smp_found_config)
+            if (smp_found_config) {
                 ioapic_phys = mp_ioapics[i].mpc_apicaddr;
+                if (!ioapic_phys) {
+                    printk(KERN_ERR
+                           "WARNING: bogus zero IO-APIC "
+                           "address found in MPTABLE, "
+                           "disabling IO/APIC support!\n");
+                    smp_found_config = 0;
+                    skip_ioapic_setup = 1;
+                    goto fake_ioapic_page;
+                }
+            } else {
+fake_ioapic_page:
+                ioapic_phys = alloc_xenheap_page();
+                ioapic_phys = __pa(ioapic_phys);
+            }
             set_fixmap_nocache(idx, ioapic_phys);
             Dprintk("mapped IOAPIC to %08lx (%08lx)\n",
                     fix_to_virt(idx), ioapic_phys);
@@ -504,32 +588,48 @@ static unsigned int __init get_8254_timer_count(void)
 {
     /*extern spinlock_t i8253_lock;*/
     /*unsigned long flags;*/
+
     unsigned int count;
+
     /*spin_lock_irqsave(&i8253_lock, flags);*/
-    outb_p(0x00, 0x43);
-    count = inb_p(0x40);
-    count |= inb_p(0x40) << 8;
+
+    outb_p(0x00, PIT_MODE);
+    count = inb_p(PIT_CH0);
+    count |= inb_p(PIT_CH0) << 8;
+
     /*spin_unlock_irqrestore(&i8253_lock, flags);*/
+
     return count;
 }
 
-void __init wait_8254_wraparound(void)
+/* next tick in 8254 can be caught by catching timer wraparound */
+static void __init wait_8254_wraparound(void)
 {
     unsigned int curr_count, prev_count=~0;
     int delta;
+
     curr_count = get_8254_timer_count();
+
     do {
         prev_count = curr_count;
         curr_count = get_8254_timer_count();
         delta = curr_count-prev_count;
+
         /*
-         * This limit for delta seems arbitrary, but it isn't, it's slightly 
-         * above the level of error a buggy Mercury/Neptune chipset timer can 
-         * cause.
+     * This limit for delta seems arbitrary, but it isn't, it's
+     * slightly above the level of error a buggy Mercury/Neptune
+     * chipset timer can cause.
          */
+
     } while (delta < 300);
 }
 
+/*
+ * Default initialization for 8254 timers. If we use other timers like HPET,
+ * we override this later
+ */
+void (*wait_timer_tick)(void) = wait_8254_wraparound;
+
 /*
  * This function sets up the local APIC timer, with a timeout of
  * 'clocks' APIC bus clock. During calibration we actually call
@@ -541,14 +641,32 @@ void __init wait_8254_wraparound(void)
  * We do reads before writes even if unnecessary, to get around the
  * P5 APIC double write bug.
  */
+
 #define APIC_DIVISOR 1
+
 static void __setup_APIC_LVTT(unsigned int clocks)
 {
-    unsigned int lvtt1_value, tmp_value;
-    lvtt1_value = SET_APIC_TIMER_BASE(APIC_TIMER_BASE_DIV)|LOCAL_TIMER_VECTOR;
-    apic_write_around(APIC_LVTT, lvtt1_value);
+    unsigned int lvtt_value, tmp_value, ver;
+
+    ver = GET_APIC_VERSION(apic_read(APIC_LVR));
+    lvtt_value = APIC_LVT_TIMER_PERIODIC | LOCAL_TIMER_VECTOR;
+    if (!APIC_INTEGRATED(ver))
+        lvtt_value |= SET_APIC_TIMER_BASE(APIC_TIMER_BASE_DIV);
+    apic_write_around(APIC_LVTT, lvtt_value);
+
+#if 0
+    /*
+     * Divide PICLK by 16
+     */
+    tmp_value = apic_read(APIC_TDCR);
+    apic_write_around(APIC_TDCR, (tmp_value
+                & ~(APIC_TDR_DIV_1 | APIC_TDR_DIV_TMBASE))
+                | APIC_TDR_DIV_16);
+#endif
+
     tmp_value = apic_read(APIC_TDCR);
     apic_write_around(APIC_TDCR, (tmp_value | APIC_TDR_DIV_1));
+
     apic_write_around(APIC_TMICT, clocks/APIC_DIVISOR);
 }
 
@@ -569,7 +687,7 @@ void setup_APIC_timer(void * data)
 /*
  * In this function we calibrate APIC bus clocks to the external timer.
  *
- * As a result we have the Bys Speed and CPU speed in Hz.
+ * As a result we have the Bus Speed and CPU speed in Hz.
  * 
  * We want to do the calibration only once (for CPU0).  CPUs connected by the
  * same APIC bus have the very same bus frequency.
@@ -586,48 +704,61 @@ int __init calibrate_APIC_clock(void)
     int i;
     const int LOOPS = HZ/10;
 
+#if 0
+    apic_printk(APIC_VERBOSE, "calibrating APIC timer ...\n");
+#endif
     printk("Calibrating APIC timer for CPU%d...\n",  smp_processor_id());
 
-    /* Put whatever arbitrary (but long enough) timeout
+    /*
+     * Put whatever arbitrary (but long enough) timeout
      * value into the APIC clock, we just want to get the
-     * counter running for calibration. */
+     * counter running for calibration.
+     */
     __setup_APIC_LVTT(1000000000);
 
-    /* The timer chip counts down to zero. Let's wait
+    /*
+     * The timer chip counts down to zero. Let's wait
      * for a wraparound to start exact measurement:
-     * (the current tick might have been already half done) */
-    wait_8254_wraparound();
+     * (the current tick might have been already half done)
+     */
 
-    /* We wrapped around just now. Let's start: */
+    wait_timer_tick();
+
+    /*
+     * We wrapped around just now. Let's start:
+     */
+    if (cpu_has_tsc)
     rdtscll(t1);
     tt1 = apic_read(APIC_TMCCT);
 
-    /* Let's wait LOOPS wraprounds: */
+    /*
+     * Let's wait LOOPS wraprounds:
+     */
     for (i = 0; i < LOOPS; i++)
-        wait_8254_wraparound();
+        wait_timer_tick();
 
     tt2 = apic_read(APIC_TMCCT);
+    if (cpu_has_tsc)
     rdtscll(t2);
 
-    /* The APIC bus clock counter is 32 bits only, it
+    /*
+     * The APIC bus clock counter is 32 bits only, it
      * might have overflown, but note that we use signed
      * longs, thus no extra care needed.
-     * underflown to be exact, as the timer counts down ;) */
-    result = (tt1-tt2)*APIC_DIVISOR/LOOPS;
+     *
+     * underflown to be exact, as the timer counts down ;)
+     */
 
-    printk("..... CPU speed is %ld.%04ld MHz.\n",
-           ((long)(t2-t1)/LOOPS) / (1000000/HZ), 
-           ((long)(t2-t1)/LOOPS) % (1000000/HZ));
+    result = (tt1-tt2)*APIC_DIVISOR/LOOPS;
 
-    printk("..... Bus speed is %ld.%04ld MHz.\n",
-           result / (1000000/HZ), 
-           result % (1000000/HZ));
+    if (cpu_has_tsc)
+        printk("..... CPU clock speed is %ld.%04ld MHz.\n",
+            ((long)(t2-t1)/LOOPS)/(1000000/HZ),
+            ((long)(t2-t1)/LOOPS)%(1000000/HZ));
 
-    /*
-     * KAF: Moved this to time.c where it's calculated relative to the TSC. 
-     * Therefore works on machines with no local APIC.
-     */
-    /*cpu_freq = (u64)(((t2-t1)/LOOPS)*HZ);*/
+    printk("..... host bus clock speed is %ld.%04ld MHz.\n",
+        result/(1000000/HZ),
+        result%(1000000/HZ));
 
     /* set up multipliers for accurate timer code */
     bus_freq   = result*HZ;
@@ -637,6 +768,7 @@ int __init calibrate_APIC_clock(void)
     printk("..... bus_scale = 0x%08X\n", bus_scale);
     /* reset APIC to zero timeout value */
     __setup_APIC_LVTT(0);
+
     return result;
 }
 
@@ -729,13 +861,17 @@ void smp_apic_timer_interrupt(struct xen_regs * regs)
     raise_softirq(AC_TIMER_SOFTIRQ);
 }
 
+
 /*
  * This interrupt should _never_ happen with our APIC/SMP architecture
  */
-asmlinkage void smp_spurious_interrupt(void)
+asmlinkage void smp_spurious_interrupt(struct xen_regs *regs)
 {
     unsigned long v;
 
+#if 0
+    irq_enter();
+#endif
     /*
      * Check if this really is a spurious interrupt and ACK it
      * if it is a vectored one.  Just in case...
@@ -748,16 +884,22 @@ asmlinkage void smp_spurious_interrupt(void)
     /* see sw-dev-man vol 3, chapter 7.4.13.5 */
     printk("spurious APIC interrupt on CPU#%d, should never happen.\n",
            smp_processor_id());
+#if 0
+    irq_exit();
+#endif
 }
 
 /*
  * This interrupt should never happen with our APIC/SMP architecture
  */
 
-asmlinkage void smp_error_interrupt(void)
+asmlinkage void smp_error_interrupt(struct xen_regs *regs)
 {
     unsigned long v, v1;
 
+#if 0
+    irq_enter();
+#endif
     /* First tickle the hardware, only then report what went on. -- REW */
     v = apic_read(APIC_ESR);
     apic_write(APIC_ESR, 0);
@@ -775,8 +917,11 @@ asmlinkage void smp_error_interrupt(void)
        6: Received illegal vector
        7: Illegal register address
     */
-    printk ("APIC error on CPU%d: %02lx(%02lx)\n",
+    Dprintk("APIC error on CPU%d: %02lx(%02lx)\n",
             smp_processor_id(), v , v1);
+#if 0
+    irq_exit();
+#endif
 }
 
 /*
@@ -785,14 +930,18 @@ asmlinkage void smp_error_interrupt(void)
  */
 int __init APIC_init_uniprocessor (void)
 {
+#if 0
+    if (enable_local_apic < 0)
+        clear_bit(X86_FEATURE_APIC, boot_cpu_data.x86_capability);
+#endif
+
     if (!smp_found_config && !cpu_has_apic)
         return -1;
 
     /*
      * Complain if the BIOS pretends there is one.
      */
-    if (!cpu_has_apic&&APIC_INTEGRATED(apic_version[boot_cpu_physical_apicid]))
-    {
+    if (!cpu_has_apic && APIC_INTEGRATED(apic_version[boot_cpu_physical_apicid])) {
         printk("BIOS bug, local APIC #%d not detected!...\n",
                boot_cpu_physical_apicid);
         return -1;
@@ -804,17 +953,26 @@ int __init APIC_init_uniprocessor (void)
 
 #ifdef CONFIG_SMP
     cpu_online_map = 1;
+#endif
+#if 0
+    phys_cpu_present_map = physid_mask_of_physid(boot_cpu_physical_apicid);
 #endif
     phys_cpu_present_map = 1;
     apic_write_around(APIC_ID, boot_cpu_physical_apicid);
 
-    apic_pm_init2();
-
     setup_local_APIC();
 
+#if 0
+    if (nmi_watchdog == NMI_LOCAL_APIC)
+        check_nmi_watchdog();
+#endif
 #ifdef CONFIG_X86_IO_APIC
-    if (smp_found_config && nr_ioapics)
+    if (smp_found_config)
+        if (!skip_ioapic_setup && nr_ioapics)
         setup_IO_APIC();
+#endif
+#if 0
+    setup_boot_APIC_clock();
 #endif
     setup_APIC_clocks();
 
diff --git a/xen/include/asm-x86/io_ports.h b/xen/include/asm-x86/io_ports.h
new file mode 100644 (file)
index 0000000..db490bd
--- /dev/null
@@ -0,0 +1,30 @@
+/*
+ *  based on linux-2.6.10/include/asm-i386/mach-default/io_ports.h
+ *
+ *  Machine specific IO port address definition for generic.
+ *  Written by Osamu Tomita <tomita@cinet.co.jp>
+ */
+#ifndef _MACH_IO_PORTS_H
+#define _MACH_IO_PORTS_H
+
+/* i8253A PIT registers */
+#define PIT_MODE              0x43
+#define PIT_CH0               0x40
+#define PIT_CH2               0x42
+
+/* i8259A PIC registers */
+#define PIC_MASTER_CMD        0x20
+#define PIC_MASTER_IMR        0x21
+#define PIC_MASTER_ISR        PIC_MASTER_CMD
+#define PIC_MASTER_POLL       PIC_MASTER_ISR
+#define PIC_MASTER_OCW3       PIC_MASTER_ISR
+#define PIC_SLAVE_CMD         0xa0
+#define PIC_SLAVE_IMR         0xa1
+
+/* i8259A PIC related value */
+#define PIC_CASCADE_IR        2
+#define MASTER_ICW4_DEFAULT   0x01
+#define SLAVE_ICW4_DEFAULT    0x01
+#define PIC_ICW4_AEOI         2
+
+#endif /* !_MACH_IO_PORTS_H */
diff --git a/xen/include/asm-x86/mach_apic.h b/xen/include/asm-x86/mach_apic.h
new file mode 100644 (file)
index 0000000..e93b080
--- /dev/null
@@ -0,0 +1,32 @@
+/*
+ *  based on linux-2.6.10/include/asm-i386/mach-default/mach_apic.h
+ *
+ */
+#ifndef __ASM_MACH_APIC_H
+#define __ASM_MACH_APIC_H
+
+#define APIC_DFR_VALUE    (APIC_DFR_FLAT)
+#define esr_disable (0)
+
+/*
+ * Set up the logical destination ID.
+ *
+ * Intel recommends to set DFR, LDR and TPR before enabling
+ * an APIC.  See e.g. "AP-388 82489DX User's Manual" (Intel
+ * document number 292116).  So here it goes...
+ */
+static inline void init_apic_ldr(void)
+{
+    unsigned long val;
+
+    apic_write_around(APIC_DFR, APIC_DFR_VALUE);
+    val = apic_read(APIC_LDR) & ~APIC_LDR_MASK;
+    val |= SET_APIC_LOGICAL_ID(1UL << smp_processor_id());
+    apic_write_around(APIC_LDR, val);
+}
+
+static inline int apic_id_registered(void)
+{
+    return test_bit(GET_APIC_ID(apic_read(APIC_ID)), &phys_cpu_present_map);
+}
+#endif /* __ASM_MACH_APIC_H */